);
$ret->neededRequests[] = $ret->createRequest;
}
- $this->fillRequests( $ret->neededRequests, self::ACTION_LOGIN, null );
+ $this->fillRequests( $ret->neededRequests, self::ACTION_LOGIN, null, true );
$session->setSecret( 'AuthManager::authnState', [
'reqs' => [], // Will be filled in later
'primary' => null,
/**
* Determine whether a particular account can be created
* @param string $username
- * @param int $flags Bitfield of User:READ_* constants
+ * @param array $options
+ * - flags: (int) Bitfield of User:READ_* constants, default User::READ_NORMAL
+ * - creating: (bool) For internal use only. Never specify this.
* @return Status
*/
- public function canCreateAccount( $username, $flags = User::READ_NORMAL ) {
+ public function canCreateAccount( $username, $options = [] ) {
+ // Back compat
+ if ( is_int( $options ) ) {
+ $options = [ 'flags' => $options ];
+ }
+ $options += [
+ 'flags' => User::READ_NORMAL,
+ 'creating' => false,
+ ];
+ $flags = $options['flags'];
+
if ( !$this->canCreateAccounts() ) {
return Status::newFatal( 'authmanager-create-disabled' );
}
$this->getPrimaryAuthenticationProviders() +
$this->getSecondaryAuthenticationProviders();
foreach ( $providers as $provider ) {
- $status = $provider->testUserForCreation( $user, false );
+ $status = $provider->testUserForCreation( $user, false, $options );
if ( !$status->isGood() ) {
return Status::wrap( $status );
}
return AuthenticationResponse::newFail( $status->getMessage() );
}
- $status = $this->canCreateAccount( $username, User::READ_LOCKING );
+ $status = $this->canCreateAccount(
+ $username, [ 'flags' => User::READ_LOCKING, 'creating' => true ]
+ );
if ( !$status->isGood() ) {
$this->logger->debug( __METHOD__ . ': {user} cannot be created: {reason}', [
'user' => $username,
}
// Denied by providers?
+ $options = [
+ 'flags' => User::READ_LATEST,
+ 'creating' => true,
+ ];
$providers = $this->getPreAuthenticationProviders() +
$this->getPrimaryAuthenticationProviders() +
$this->getSecondaryAuthenticationProviders();
foreach ( $providers as $provider ) {
- $status = $provider->testUserForCreation( $user, $source );
+ $status = $provider->testUserForCreation( $user, $source, $options );
if ( !$status->isGood() ) {
$ret = Status::wrap( $status );
$this->logger->debug( __METHOD__ . ': Provider denied creation of {username}: {reason}', [
throw $ex;
}
- $this->setDefaultUserOptions( $user, true );
+ $this->setDefaultUserOptions( $user, false );
// Inform the providers
$this->callMethodOnProviders( 6, 'autoCreatedAccount', [ $user, $source ] );
$logid = $logEntry->insert();
}
+ // Commit database changes, so even if something else later blows up
+ // the newly-created user doesn't get lost.
+ wfGetLBFactory()->commitMasterChanges( __METHOD__ );
+
if ( $login ) {
$this->setSessionDataForUser( $user );
}
}
// Fill in reqs data
- $this->fillRequests( $reqs, $providerAction, $options['username'] );
+ $this->fillRequests( $reqs, $providerAction, $options['username'], true );
// For self::ACTION_CHANGE, filter out any that something else *doesn't* allow changing
if ( $providerAction === self::ACTION_CHANGE || $providerAction === self::ACTION_REMOVE ) {
* @param AuthenticationRequest[] &$reqs
* @param string $action
* @param string|null $username
+ * @param boolean $forceAction
*/
- private function fillRequests( array &$reqs, $action, $username ) {
+ private function fillRequests( array &$reqs, $action, $username, $forceAction = false ) {
foreach ( $reqs as $req ) {
- $req->action = $action;
+ if ( !$req->action || $forceAction ) {
+ $req->action = $action;
+ }
if ( $req->username === null ) {
$req->username = $username;
}
return true;
}
+ /**
+ * Get a provider by ID
+ * @note This is public so extensions can check whether their own provider
+ * is installed and so they can read its configuration if necessary.
+ * Other uses are not recommended.
+ * @param string $id
+ * @return AuthenticationProvider|null
+ */
+ public function getAuthenticationProvider( $id ) {
+ // Fast version
+ if ( isset( $this->allAuthenticationProviders[$id] ) ) {
+ return $this->allAuthenticationProviders[$id];
+ }
+
+ // Slow version: instantiate each kind and check
+ $providers = $this->getPrimaryAuthenticationProviders();
+ if ( isset( $providers[$id] ) ) {
+ return $providers[$id];
+ }
+ $providers = $this->getSecondaryAuthenticationProviders();
+ if ( isset( $providers[$id] ) ) {
+ return $providers[$id];
+ }
+ $providers = $this->getPreAuthenticationProviders();
+ if ( isset( $providers[$id] ) ) {
+ return $providers[$id];
+ }
+
+ return null;
+ }
+
/**@}*/
/**
return $this->secondaryAuthenticationProviders;
}
- /**
- * Get a provider by ID
- * @param string $id
- * @return AuthenticationProvider|null
- */
- protected function getAuthenticationProvider( $id ) {
- // Fast version
- if ( isset( $this->allAuthenticationProviders[$id] ) ) {
- return $this->allAuthenticationProviders[$id];
- }
-
- // Slow version: instantiate each kind and check
- $providers = $this->getPrimaryAuthenticationProviders();
- if ( isset( $providers[$id] ) ) {
- return $providers[$id];
- }
- $providers = $this->getSecondaryAuthenticationProviders();
- if ( isset( $providers[$id] ) ) {
- return $providers[$id];
- }
- $providers = $this->getPreAuthenticationProviders();
- if ( isset( $providers[$id] ) ) {
- return $providers[$id];
- }
-
- return null;
- }
-
/**
* @param User $user
* @param bool|null $remember
private function setDefaultUserOptions( User $user, $useContextLang ) {
global $wgContLang;
- \MediaWiki\Session\SessionManager::singleton()->invalidateSessionsForUser( $user );
+ $user->setToken();
$lang = $useContextLang ? \RequestContext::getMain()->getLanguage() : $wgContLang;
$user->setOption( 'language', $lang->getPreferredVariant() );